package com.chasmcity.munrobagging.map;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;

import com.chasmcity.munrobagging.model.LatLong;
import com.chasmcity.munrobagging.model.LatLongBoundingBox;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;

/**
 * TODO: Missing class description for StopsMap!
 * <p>
 * &copy; Copyright 2010 Kizoom Ltd.
 * <p>
 * $Id: StopsMapView.java,v 1.27 2011/02/20 12:50:44 kennym Exp $
 */
public class ImprovedMapView extends MapView {
	
	private MyLocationOverlay myLocationOverlay;
	
	private MapMovementListener mapMovementListener;
	
	private volatile GeoPoint lastNotifiedCentrePoint;
	private volatile Integer lastNotifiedZoomLevel;
	
	private volatile boolean touchIsDown = false;
	
	public ImprovedMapView(Context context, AttributeSet attributeSet) {
		super(context, attributeSet);
		setClickable(true);
	}
	
	public void init() {
		setBuiltInZoomControls(true);
        
        myLocationOverlay = new MyLocationOverlay(getContext(), this);
        getOverlays().add(myLocationOverlay);
	}
	
	public void enableMyLocation() {
		myLocationOverlay.enableMyLocation();
	}
	
	public void disableMyLocation() {
		myLocationOverlay.disableMyLocation();
	}
	
	/**
	 * Centers the map on a location.
	 * @param latLong
	 * @param animate should only be true if you know the map is already visible
	 */
	public void goTo(LatLong latLong, int zoom, boolean animate) {
		if (animate) {
			getController().animateTo(latLong.asGeoPoint());
		} else {
			getController().setCenter(latLong.asGeoPoint());
		}
		getController().setZoom(zoom);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			touchIsDown = true;
		}
		if (event.getAction() == MotionEvent.ACTION_UP) {
			touchIsDown = false;
		}
		return super.onTouchEvent(event);
	}
	
	public void setMapMovementListener(MapMovementListener mapMovementListener) {
		this.mapMovementListener = mapMovementListener;
	}
	
	@Override
	public void computeScroll() {
		super.computeScroll();
		
		if (mapMovementListener != null) {
			GeoPoint centrePoint = getMapCenter();
			int zoomLevel = getZoomLevel();
			
			if (!touchIsDown) {
				boolean centrePointHasChanged = lastNotifiedCentrePoint == null || !lastNotifiedCentrePoint.equals(centrePoint);
				boolean zoomHasChanged = lastNotifiedZoomLevel == null || !lastNotifiedZoomLevel.equals(zoomLevel);
				
				if (centrePointHasChanged || zoomHasChanged) {
					mapMovementListener.mapMoved(getMapSpanBoundingBox(), getZoomLevel());
				}
				lastNotifiedCentrePoint = centrePoint;
				lastNotifiedZoomLevel = zoomLevel;
			}
		}
	}
	
	public LatLongBoundingBox getMapSpanBoundingBox() {
		GeoPoint mapCenter = getMapCenter();
		int latitudeSpan = getLatitudeSpan();
		int longitudeSpan = getLongitudeSpan();
		
		LatLong swCorner = new LatLong(
				(mapCenter.getLatitudeE6() - (latitudeSpan/2)) / 1E6, 
				(mapCenter.getLongitudeE6() - (longitudeSpan/2)) / 1E6
		);
		LatLong neCorner = new LatLong(
				(mapCenter.getLatitudeE6() + (latitudeSpan/2)) / 1E6, 
				(mapCenter.getLongitudeE6() + (longitudeSpan/2)) / 1E6
		);
		
		return new LatLongBoundingBox(swCorner, neCorner);
	}
	
	public interface MapMovementListener {
		void mapMoved(LatLongBoundingBox newBoundingBox, int newZoomLevel);
	}
	
	public interface MarkerSelectionListener<M> {
		void stopSelected(M stop);
	}
}
